package com.wy.component.security;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.log4j.Logger;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class AesUtil {

    private byte[] initVector = { 0x32, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,
            0x38, 0x27, 0x36, 0x35, 0x33, 0x23, 0x32, 0x31 };

        private static String cKey = "30e19919d30d4c5e";
        
        /**
         * FIXME For demo only, should rewrite this method in your product environment!
         * 
         * @param appid
         * @return
         */
        public static String findKeyById(String appid) {
          // Fake key.
          String key = "12345678901234567890123456789012";
          return key;
        }

        // 加密
          public static String encrypt(String sSrc) throws Exception {
              byte[] raw = cKey.getBytes("UTF-8");
              SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
              Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//"算法/模式/补码方式"
              IvParameterSpec iv = new IvParameterSpec("0102030405060708".getBytes("UTF-8"));//使用CBC模式，需要一个向量iv，可增加加密算法的强度
              cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
              byte[] encrypted = cipher.doFinal(sSrc.getBytes("UTF-8"));
              return byte2hex(encrypted);//此处使用BASE64做转码功能，同时能起到2次加密的作用。
          }

      	public static String byte2hex(byte[] b) {
      		String hs = "";
      		String stmp = "";
      		for (int n = 0; n < b.length; n++) {
      			stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
      			if (stmp.length() == 1) {
      				hs = hs + "0" + stmp;
      			} else {
      				hs = hs + stmp;
      			}
      		}
      		return hs.toUpperCase();
      	}
      	
          // 解密
          public static String decrypt(String sSrc) throws Exception {
              try {
                  byte[] raw = cKey.getBytes("UTF-8");
                  SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
                  Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                  IvParameterSpec iv = new IvParameterSpec("0102030405060708"
                          .getBytes("UTF-8"));
                  cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
                  byte[] encrypted1 = hexStringToBytes(sSrc);//先用base64解密
                  try {
                      byte[] original = cipher.doFinal(encrypted1);
                      String originalString = new String(original,"UTF-8");
                      return originalString;
                  } catch (Exception e) {
                      System.out.println(e.toString());
                      return null;
                  }
              } catch (Exception ex) {
                  System.out.println(ex.toString());
                  return null;
              }
          }

      	public static byte[] hexStringToBytes(String hexString) {
      		if (hexString == null || hexString.equals("")) {
      			return null;
      		}
      		hexString = hexString.toUpperCase();
      		int length = hexString.length() / 2;
      		char[] hexChars = hexString.toCharArray();
      		byte[] d = new byte[length];
      		for (int i = 0; i < length; i++) {
      			int pos = i * 2;
      			d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));

      		}
      		return d;
      	}
      	
      	private static byte charToByte(char c) {
      		return (byte) "0123456789ABCDEF".indexOf(c);
      	}
    	
        public static void main(String[] args) throws Exception {
        	System.out.println(encrypt("你好"));
        	System.out.println(decrypt("2fb5ee66b9ad63366b5266066c62fff3"));
            /*
             * 加密用的Key 可以用26个字母和数字组成，最好不要用保留字符，虽然不会错，至于怎么裁决，个人看情况而定
             * 此处使用AES-128-CBC加密模式，key需要为16位。
             */
            // 需要加密的字串
//            String cSrc = "你好";
//            System.out.println(cSrc);
//            // 加密
//            long lStart = System.currentTimeMillis();
//            String enString = AesUtil.Encrypt(cSrc, cKey);
//            System.out.println("加密后的字串是：" + enString);
//
//            long lUseTime = System.currentTimeMillis() - lStart;
//            System.out.println("加密耗时：" + lUseTime + "毫秒");
//            // 解密
//            lStart = System.currentTimeMillis();
//            String DeString = AesUtil.decrypt("0Vg5OzsiBs87jR2lMAx+jQ==", cKey);
//            System.out.println("解密后的字串是：" + DeString);
//            lUseTime = System.currentTimeMillis() - lStart;
//            System.out.println("解密耗时：" + lUseTime + "毫秒");
            
        }
}
